#include <iostream>
#include "calculator.h"
#include <cctype>      // 用于字符类型检查 (isdigit, isspace)
#include <stdexcept>   // 用于标准异常类 (std::runtime_error)
#include <iomanip>     // 用于格式化输出 (std::fixed, std::setprecision)

// 前向声明解析器函数
// 这样，函数可以互相调用，即使它们在定义顺序上是“倒置”的
double parseExpression(const std::string& input, size_t& pos);
double parseTerm(const std::string& input, size_t& pos);
double parseFactor(const std::string& input, size_t& pos);

// 辅助函数：跳过当前位置的所有空白字符
void skipWhitespace(const std::string& input, size_t& pos) 
{
    while (pos < input.length() && std::isspace(input[pos])) {
        pos++;
    }
}

// 辅助函数：从字符串中解析一个浮点数
double parseNumber(const std::string& input, size_t& pos) 
{
    skipWhitespace(input, pos); // 先跳过数字前的空白

    size_t start_pos = pos;
    // 允许数字以小数点开头，例如 ".5"
    if (pos < input.length() && input[pos] == '.') {
        pos++;
    }
    // 读取整数部分
    while (pos < input.length() && std::isdigit(input[pos])) {
        pos++;
    }
    // 读取小数部分
    if (pos < input.length() && input[pos] == '.') {
        pos++;
        while (pos < input.length() && std::isdigit(input[pos])) {
            pos++;
        }
    }

    // 如果没有读取到任何数字字符（包括小数点），则抛出错误
    if (pos == start_pos || (pos == start_pos + 1 && input[start_pos] == '.' && (pos == input.length() || !std::isdigit(input[pos])))) {
        throw std::runtime_error("Invalid number format at position " + std::to_string(start_pos));
    }

    // 使用 stod 将子字符串转换为 double
    // 注意：stod 会自动处理空白，但已经手动处理了，所以这里传入的子字符串应该不含前导空白
    // 并且 stod 会自动处理数字解析失败的情况，但已经做了初步检查
    try {
        double value = std::stod(input.substr(start_pos, pos - start_pos));
        return value;
    } catch (const std::out_of_range& e) {
        throw std::runtime_error("Number out of range at position " + std::to_string(start_pos));
    } catch (const std::invalid_argument& e) {
        // 理论上，由于前面的isdigit检查，这里不应该发生
        throw std::runtime_error("Invalid number format (stod error) at position " + std::to_string(start_pos));
    }
}

// 解析因子：数字或括号内的表达式
// 语法规则：factor = number | "(" expression ")"
double parseFactor(const std::string& input, size_t& pos) 
{
    skipWhitespace(input, pos); // 跳过因子前的空白

    if (pos >= input.length()) {
        throw std::runtime_error("Unexpected end of expression.");
    }

    char current_char = input[pos];

    // 如果是数字，直接解析数字
    if (std::isdigit(current_char) || current_char == '.') {
        return parseNumber(input, pos);
    }
    // 如果是左括号，递归解析括号内的表达式
    else if (current_char == '(') {
        pos++; // 跳过 '('
        double result = parseExpression(input, pos); // 递归调用 parseExpression
        skipWhitespace(input, pos); // 跳过右括号前的空白

        if (pos >= input.length() || input[pos] != ')') {
            throw std::runtime_error("Mismatched parentheses: Expected ')' at position " + std::to_string(pos));
        }
        pos++; // 跳过 ')'
        return result;
    }
    // 如果是负号，处理负数
    else if (current_char == '-') {
        pos++; // 跳过 '-'
        return -parseFactor(input, pos); // 递归解析负号后面的因子
    }
    // 未预期的字符
    else {
        throw std::runtime_error("Unexpected character '" + std::string(1, current_char) + "' at position " + std::to_string(pos));
    }
}

// 解析项：乘法和除法
// 语法规则：term = factor { ("*" | "/") factor }
double parseTerm(const std::string& input, size_t& pos) 
{
    double result = parseFactor(input, pos); // 首先解析一个因子

    skipWhitespace(input, pos); // 跳过运算符前的空白

    while (pos < input.length()) {
        char op = input[pos];
        if (op == '*' || op == '/') {
            pos++; // 跳过运算符
            double next_factor = parseFactor(input, pos); // 解析下一个因子

            if (op == '*') {
                result *= next_factor;
            } else { // op == '/'
                if (next_factor == 0.0) {
                    throw std::runtime_error("Division by zero at position " + std::to_string(pos - 1));
                }
                result /= next_factor;
            }
            skipWhitespace(input, pos); // 跳过下一个运算符前的空白
        } else {
            break; // 不是乘除运算符，停止循环
        }
    }
    return result;
}

// 解析表达式：加法和减法
// 语法规则：expression = term { ("+" | "-") term }
double parseExpression(const std::string& input, size_t& pos) 
{
    double result = parseTerm(input, pos); // 首先解析一个项

    skipWhitespace(input, pos); // 跳过运算符前的空白

    while (pos < input.length()) {
        char op = input[pos];
        if (op == '+' || op == '-') {
            pos++; // 跳过运算符
            double next_term = parseTerm(input, pos); // 解析下一个项

            if (op == '+') {
                result += next_term;
            } else { // op == '-'
                result -= next_term;
            }
            skipWhitespace(input, pos); // 跳过下一个运算符前的空白
        } else {
            break; // 不是加减运算符，停止循环
        }
    }
    return result;
}

// 主计算函数：封装整个解析和求值过程
double calculate(const std::string& expression) 
{
    size_t pos = 0; // 初始化解析位置
    double result = parseExpression(expression, pos); // 从解析表达式开始

    skipWhitespace(expression, pos); // 在表达式末尾跳过任何剩余的空白

    // 最终检查：确保在表达式求值完毕后，pos 已经到达字符串末尾
    // 否则表示有未处理的“垃圾”字符
    if (pos < expression.length()) {
        throw std::runtime_error("Unexpected characters at end of expression: '" + expression.substr(pos) + "' at position " + std::to_string(pos));
    }

    return result;
}
